package mireille.learning.devoir1;


import mireille.learning.devoir1.Exceptions.OperationPourCrediterNonAutoriseException;
import mireille.learning.devoir1.Exceptions.DebitNonAutoriseException;

/**
 * <p>Programme permettant de gérer les comptes bancaires</p>
 * <p>La classe compte bancaire est abstraite</p>
 *
 * @author Mireille Tepounnou
 */
public abstract class CompteBancaire implements Comparable<CompteBancaire> {

    private String nom;
    private String adresse;
    private int numero;
    private double solde;
    /**
     * Pour gérer l'incrémentation automatique du numéro de compte, nous avons
     * créé un attribut nommé NEXTNUMBER qui est initialisé au départ
     * (ci-dessous) à 0.
     */
    public static int NEXTNUMBER = 0;


    /**
     * Constructeur du compte bancaire. Le solde initial est égal a zéro et le
     * numéro de compte est automatiquement incrémenté de 1.
     *
     * @param nom nom du compte
     * @param adresse adresse du compte
     */
    public CompteBancaire(String nom, String adresse){
        this.nom = nom;
        this.adresse = adresse;
        this.numero = CompteBancaire.NEXTNUMBER;
        this.solde = 0;
        // incrémention automatique du champ de classe (compteur)
        NEXTNUMBER++;
    }

    /**
     * Implémentation de la méthode abstraite de traitement quotidien ; c'est à
     * dire le traitement effectué tous les jours sur tous les comptes par le
     * programme.
     */
    public abstract void traitementQuotidien()throws OperationPourCrediterNonAutoriseException, DebitNonAutoriseException;

    /**
     * Méthode pour verser de l'argent dans le compte.
     *
     * @param montant montant à créditer
     *
     */
    public void crediter(double montant) throws OperationPourCrediterNonAutoriseException {

        if (montant < 0) {
            throw new OperationPourCrediterNonAutoriseException ("Saisir un montant positif s'il vous plaît.");
        } else {
            solde = solde + montant;
        }
    }
      
    /**
     * Méthode pour retirer de l'argent du compte.
     *
     * @param montant montant à débiter
     */
    public void debiter(double montant) throws DebitNonAutoriseException {
        if (montant < 0) {
            throw new DebitNonAutoriseException ("Saisir un montant positif s'il vous plaît.");
        } else {
            solde = solde - montant;
        }
    }

    /**
     * Méthode pour obtenir l'adresse du compte. Le mot clé final a été ajouté
     * pour optimiser l'appel de cette méthode en empêchant sa redéfinition dans
     * les classes filles.
     *
     * @return
     */
    public final String getAdresse() {
        return this.adresse;
    }

    /**
     * Méthode pour obtenir le nom du compte. Le mot clé final a été ajouté pour
     * optimiser l'appel de cette méthode en empêchant sa redéfinition dans les
     * classes filles.
     *
     * @return
     */
    public final String getNom() {
        return this.nom;
    }

    /**
     * Méthode pour obtenir le numero du compte. Le mot clé final a été ajouté
     * pour optimiser l'appel de cette méthode en empêchant sa redéfinition dans
     * les classes filles.
     *
     * @return
     */
    public final int getNumero() {
        return this.numero;
    }

    /**
     * Méthode pour obtenir le solde du compte. Le mot clé final a été ajouté
     * pour optimiser l'appel de cette méthode en empêchant sa redéfinition dans
     * les classes filles.
     *
     * @return
     */
    public final double getSolde() {
        return this.solde;
    }

    /**
     * Méthode pour attribuer une adresse au compte. Le mot clé final a été
     * ajouté pour optimiser l'appel de cette méthode en empêchant sa
     * redéfinition (surcharge) dans les classes filles.
     *
     * @param adresse adresse du compte
     */
    public final void setAdresse(String adresse) {
        this.adresse = adresse;
    }

    /**
     * Méthode pour attribuer un nom au compte. Le mot clé final a été ajouté
     * pour optimiser l'appel de cette méthode en empêchant sa redéfinition dans
     * les classes filles.
     *
     * @param nom nom du compte
     */
    public final void setNom(String nom) {
        this.nom = nom;
    }

    /**
     * Méthode qui décrit l’ensemble des comptes sous forme d’une chaîne de
     * caractères, un compte par ligne.
     *
     * @return
     */
    @Override
    public String toString() {
        String str = "	Le numéro du compte est " + this.getNumero()
                + "\n" + "	Le nom du compte est " + this.getNom()
                + "\n" + "	L'adresse du compte est " + this.getAdresse()
                + "\n" + "	Le solde est de " + this.getSolde() + " euro";

        return str;
    }

    /**
     * Redéfinissons la méthode pour tester l'égalité entre les comptes
     * bancaires.
     *
     * @param obj objet qui doit être comparé
     * @return la méthode rend true (vrai) en cas d'égalité entre les
     * références ; autrement, elle rend false (faux).
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof CompteBancaire) {
            if (this.numero == ((CompteBancaire) obj).getNumero()) {
                return true;
            } else {
                return false;
            }

        } else {
            return false;
        }
    }


    /**
     * Redéfinissons la méthode compareTo de l'interface Comparable. Cette
     * méthode sera utilisée par la méthode "sort" qui va effectuer le tri.
     *
     * @param objectToCompare
     * @return Rend: 0 si cet objet est égale à l'objet à comparer
     * (objectToCompare), 1 si cet objet est supérieur à l'objet à comparer
     * (objectToCompare), -1 si cet objet est inférieur à l'objet à comparer
     * (objectToCompare),
     * @throws NullPointerException si l'objet à comparer est null
     */
    @Override
    public int compareTo(CompteBancaire objectToCompare) {
        if (objectToCompare == null) {
            throw new NullPointerException();
        }
        if (this == objectToCompare) {
            return 0;
        }
        if (this.numero == objectToCompare.getNumero()) {
            return 0;
        } else if (this.numero > objectToCompare.getNumero()) {
            return 1;
        } else {
            return -1;
        }
    }
}
